import { routerRedux } from 'dva/router';
import {
    getLogList,
    getDepList, addDep, updateDep, delDep,
    getGlobalMenuList, getRoleMenuList, getRoleList, addRole, updateRole, delRole,
    getUserList, getUserDetail, addUser, updateUser, delUsers,
    upload, updatePwd
} from '../services/permissionService';
import moment from 'moment';

const initialState = {
    depList:[],
    currentDep:{},
    expandedKeys:[],
    roleList:[],
    globalMenuList:[],
    currentPage:1,
    total:0,
    checkedStatus:{},
    selectedIds:[],
    userList:[],
    optional:{},
    isLoading:false,
    logList:[]
};

export default {
    namespace: 'permission',
    state: initialState,
    effects: {
        *fetchDepList(action, { call, put, select }){
            let { user:{ companyId }} = yield select();
            let { data } = yield call(getDepList, { companyId });
            if ( data && data.code === 200 ) {
                yield put({ type:'getDepListResult', payload:{ data:data.data }});
            }
        },
        *addDepAsync(action, { call, put, select }){
            let { user:{ companyId }} = yield select();
            let { resolve, reject, deptName, deptId, parentDeptId, forEdit } = action.payload || {};
            let { data } = yield call( forEdit ? updateDep : addDep, { companyId, deptName, deptId, parentDeptId });
            if ( data && data.code === 200 ){
                yield put({ type:'fetchDepList'});
                if ( resolve ) resolve();
            } else {
                if ( reject ) reject(data.message);
            }
        },
        *delDepAsync(action, { call, put, select }){
            let { permission:{ currentDep }} = yield select();
            let { resolve, reject } = action.payload || {};
            let { data } = yield call(delDep, { deptId:currentDep.deptId });
            if ( data && data.code === 200 ){
                yield put({ type:'fetchDepList'});
                if ( resolve ) resolve();
            } else {
                if ( reject ) reject(data.message);
            }
        },
        *fetchGlobalMenuList(action, { call, put, select }){
            let { data } = yield call(getGlobalMenuList);
            if ( data && data.code === 200 ){
                yield put({ type:'getGlobalMenuListResult', payload:{ data:data.data }});
            }
        },
        *fetchRoleMenuList(action, { call, put, select }){
            let { roleId } = action.payload || {};
            let { data } = yield call(getRoleMenuList, { roleId });
            if ( data && data.code === 200 ){
                yield put({ type:'setRoleMenu', payload:{ data:data.data }});
            }
        },
        *fetchRoleList(action, { call, put, select }){
            let { currentPage } = action.payload || {};
            currentPage = currentPage || 1;
            let { data } = yield call(getRoleList, { page:currentPage, pageSize:12 });
            if ( data && data.code === 200 ){
                yield put({ type:'getRoleListResult', payload:{ data:data.data }});
            }   
        },
        *addRoleAsync(action, { call, put, select }){
            let { user:{ companyId }, permission:{ checkedStatus }} = yield select();
            let { resolve, reject, roleName, remark, roleId, forEdit } = action.payload || {};
            let sysMenuIds = [];
            Object.keys(checkedStatus).forEach(menuId=>{
                if ( checkedStatus[menuId].status ) {
                    sysMenuIds.push(menuId);
                }
            })
            let { data } = yield call(forEdit ? updateRole : addRole, { companyId, roleId, roleName, remark, sysMenuIds });
            if ( data && data.code === 200 ){
                yield put({ type:'fetchRoleList'});
                if ( resolve ) resolve();
            } else {
                if ( reject ) reject(data.message);
            }
        },
        *delRoleAsync(action, { call, put, select }){
            let { resolve, reject, roleId } = action.payload || {};
            let { data } = yield call(delRole, { roleId });
            if ( data && data.code === 200 ){
                yield put({ type:'fetchRoleList'});
                if ( resolve ) resolve();
            } else {
                if ( reject ) reject(data.message);
            }
        },
        *fetchUserList(action, { call, put, select }){
            let { user:{ companyId }, permission:{ optional }} = yield select();
            let { currentPage } = action.payload || {};
            currentPage = currentPage || 1;
            let obj = { companyId, page:currentPage, pageSize:12 };
            Object.keys(optional).forEach(key=>{
                if ( optional[key] && optional[key] !== 'all' ) {
                    obj[key] = optional[key];
                }
            })
            let { data } = yield call(getUserList, obj );
            if ( data && data.code === 200 ){
                yield put({ type:'getUserListResult', payload:{ data:data.data, currentPage, total:data.total }});
            }
        },
        *fetchUserDetail(action, { call, put, select }){
            let { resolve, reject, employeeId } = action.payload || {};
            let { data } = yield call(getUserDetail, { employeeId });
            if ( data && data.code === 200 ){
                if ( resolve ) resolve(data.data);
            } else {
                if ( reject ) reject(data.message);
            }
        },
        *addUserAsync(action, { call, put, select, all }){
            let { user:{ companyId }, permission:{ currentDep }} = yield select();
            let { values, resolve, reject, forEdit } = action.payload || {};
            values.companyId = companyId;
            values.companyName = '测试公司';
            values.deptId = currentDep.deptId;
            if ( values.fileList ) {
                let imagePaths = yield all([
                    ...values.fileList.map((file) => call(upload, { file, uploadType:'headshot' })),
                ]);
                if ( imagePaths && imagePaths.length) {
                    imagePaths = imagePaths.map((i) => i.data.data);
                    values.headshot = imagePaths[0].photoPath;
                }
                values.fileList = null;
            }
            let obj = {};
            Object.keys(values).forEach(key=>{
                if ( values[key] || typeof values[key] === 'number' ) {
                    obj[key] = values[key];
                }
            })
            let { data } = yield call(forEdit ? updateUser : addUser, obj);
            if ( data && data.code === 200 ){
                yield put({ type:'fetchUserList'});
                if ( resolve ) resolve();
            } else {
                if ( reject ) reject(data.message);
            }
        },
        *fetchRoleList(action, { call, put }){
            let data = yield call(getRoleList);
            if ( data && data.code === 200 ){
                yield put({type:'getRoleListResult', payload:{data:data.data }});
            }
        },
        *updatePwdAsync(action, { call, put, select }){
            let { user:{ userInfo }} = yield select();
            let { values, resolve, reject } = action.payload; 
            let data = yield call(updatePwd, { userId:userInfo.userId, userName:userInfo.userName, oldPassword:values.oldPassword, newPassword:values.newPassword });
            if ( data && data.code === 200 ) {
                if ( resolve && typeof resolve === 'function') resolve();
            } else {
                if ( reject ) reject(data.message);
            }
        },
        *fetchLogList(action, { call, put, select }){
            let { user:{ companyId }} = yield select();
            let { currentPage, userName, logType  } = action.payload || {};
            currentPage = currentPage || 1;
            let params = { companyId, page:currentPage, pageSize:12, operateUserName:userName };
            if ( userName ) {
                params.operateUserName = userName;
            }
            if ( logType && logType === 'login' ) {
                params.operateType = '登录';
            }
            yield put({ type:'toggleLoading'});
            let { data, code, message, total } = yield call(getLogList, params);
            if ( code === 200 ){
                yield put({ type:'getLogListResult', payload:{ data, currentPage, total }});
            }
        }
        
    },
    reducers: {
        toggleLoading(state){
            return { ...state, isLoading:true };
        },
        getDepListResult(state, { payload:{ data }}){
            // 初始化部门列表
            let arr = data.length ? data : [{ createTime:new Date().toISOString().slice(0, 19), deptId:1, deptName:'全厂', parentId:null }];
            let expandedKeys = [];
            formatTreeData(arr, expandedKeys);
            return { ...state, depList:arr, currentDep:arr[0], expandedKeys };
        },
        getUserListResult(state, { payload:{ data, currentPage, total }}){
            return { ...state, userList:data, currentPage, total };
        },
        getLogListResult(state, { payload:{ data, currentPage, total }}){
            return { ...state, logList:data, currentPage, total, isLoading:false };
        },
        setOptional(state, { payload }){
            return { ...state, optional:payload };
        },
        setCurrentDep(state, { payload }){
            return { ...state, currentDep:payload };
        },
        setExpandedKeys(state, { payload }){
            return { ...state, expandedKeys:payload }
        },
        getRoleListResult(state, { payload:{ data }}){
            return { ...state, roleList:data };
        },
        getGlobalMenuListResult(state, { payload:{ data }}){
            // 设置所有菜单和功能按钮的初始状态为选中状态
            let obj = {};
            getCheckedStatus(data, obj);
            return { ...state, globalMenuList:data, checkedStatus:obj };
        },
        setRoleMenu(state, { payload:{ data, reset }}){
            let obj = {};
            let selectedIds = data.map(i=>i.menuId + '');
            Object.keys(state.checkedStatus).forEach(menuId=>{
                if ( reset || selectedIds.includes(menuId) ){
                    obj[menuId] = { ...state.checkedStatus[menuId], status:true };
                } else {
                    obj[menuId] = { ...state.checkedStatus[menuId], status:false };
                }
            });            
            return { ...state, checkedStatus:obj };
        },
        setCheckedStatus(state, { payload }){
            let subMenuIds = state.checkedStatus[payload].children;
            let prevStatus = state.checkedStatus[payload].status;
            let nodes = [payload];         
            subMenuIds.forEach(menuId=>{
                nodes.push(menuId);
                if ( state.checkedStatus[menuId].children && state.checkedStatus[menuId].children.length ) {
                    state.checkedStatus[menuId].children.forEach(i=>{
                        nodes.push(i);
                    
                    })
                }
            })   
            let obj = { ...state.checkedStatus };
            nodes.forEach(menuId=>{
                obj[menuId] = { ...state.checkedStatus[menuId], status:!prevStatus };
            })
            return { ...state, checkedStatus:obj }
        }
        
    }
};

function formatTreeData(arr, expandedKeys){
    arr.forEach(item=>{
        item.title = item.deptName;
        item.key = item.deptId;
        item.children = item.subordinate;
        expandedKeys.push(item.deptId);
        if ( item.children && item.children ) {
            formatTreeData(item.children, expandedKeys);
        }
    })
}

function getCheckedStatus(arr, obj){
    arr.forEach(item=>{
        obj[item.menuId] = { status:true, children:item.subMenu ? item.subMenu.map(i=>i.menuId) : [] };
        if ( item.subMenu && item.subMenu.length ) {
            getCheckedStatus(item.subMenu, obj);
        }
    })
}